#include "game_cron.h"
#include "ccronexpr.h"
#include <cstring>
#include "game_log.h"
#include "game_util.h"

CGameCron g_CGameCron;

BOOL CGameCron::init(event_base* evbase){
  _evbase = evbase;
  _event = event_new(_evbase,-1,0,CGameCron::__timer_cb,this);
  tick();
  return TRUE;
}

void CGameCron::__timer_cb(int sock, short which, void *arg){
  CGameCron* This = (CGameCron*)arg;     
  This->onTick();    
}

BOOL CGameCron::next(UINT64* dest,UINT64 now,const char* cronexpr){
  cron_expr expr;
  const char* err = NULL;
  memset(&expr, 0, sizeof(expr));
  // cron_parse_expr("0 */2 1-4 * * *", &expr, &err);
  cron_parse_expr(cronexpr, &expr, &err);
  if (err) {
    CC_WARN("CGameCron","%s",err);
    // delete err;
    return FALSE;
  }
  time_t next = cron_next(&expr, now);
  memcpy(dest,&next,sizeof(UINT64));
  return TRUE;
}

BOOL CGameCron::next(UINT64* dest,const char* cronexpr){
  
  time_t now = time(NULL);
  return next(dest,now,cronexpr);
  
}

void CGameCron::tick(){
  timeval tv = {.tv_sec = 0,.tv_usec = 1000000};

  event_add(_event,&tv);
}

void CGameCron::onTick(){
  time_t now = time(NULL);
  for(std::map<std::string,Cron_t*>::iterator itr = _map.begin();itr != _map.end();itr++){
    Cron_t* t = itr->second;
    UINT64 time;
    if(!next(&time,t->_last,t->_cronexpr.c_str()))
      continue;

    // char date[64] = {0};
    // char date1[64] = {0};
    // __localtime_format(now,date1,"%F %H:%M:%S");
    // __localtime_format(time,date,"%F %H:%M:%S");
    // CC_LOG("CGameCron","cronexpr: %s,now: %s(%d),next: %s(%d)",t->_cronexpr.c_str(),date1,now,date,time);

    if(now >= time){
      t->_last = now;
      t->_func();
    }
    
  }
  tick();
}

BOOL CGameCron::init(){
  return init(g_CGameEV.getBase());
}


void CGameCron::cron(const std::function<void()>& fn,const std::string& cronexpr){
  cron(fn,cronexpr,cronexpr);
}

void CGameCron::cron(const std::function<void()>& fn,const std::string& cronexpr,const std::string& key){
  Cron_t* t = new Cron_t();
  t->_last = time(NULL);
  t->_cronexpr = cronexpr;
  t->_func = fn;
  _map.insert(std::make_pair(key,t));
}

void CGameCron::uncron(const std::string& key){
  
}
